#include "TimedLoopCommandManager.h"

#include <fstream>

#include "common.h"
#include "SafeDataFile.h"
#include "LoopManager.h"

TimedLoopCommandManager::TimedLoopCommandManager():mpath(TIMED_COMMAND_CONFIG) {
    load();
}

TimedLoopCommandManager::~TimedLoopCommandManager() {
    //dtor
}


LoopControlInfoPtr TimedLoopCommandManager::load() {
    std::error_code errorCode;
    uintmax_t size = std::filesystem::file_size(mpath, errorCode);

    if (0 < size && !errorCode) {
        std::ifstream inputStream(mpath);
        char buffer[size];
        inputStream.read(buffer, sizeof (buffer));
        LoopControlInfo* pTemp = reinterpret_cast <LoopControlInfo*>(buffer);

        mptimedLoopCommand.reset(new(pTemp->length) LoopControlInfo(*pTemp), LoopControlInfo::releaseMemory);

        inputStream.close();
    }

    return mptimedLoopCommand;
}



LoopControlInfoPtr TimedLoopCommandManager::load(const DateTimeUtility::ClockTime_t& time) {
    if (!mptimedLoopCommand) {
        load();

        if (!mptimedLoopCommand) {
            return mptimedLoopCommand;
        }
    }

    if (time < mptimedLoopCommand->beginTime + mptimedLoopCommand->duration) {
        return mptimedLoopCommand;
    } else {
        return nullptr;
    }
}



bool TimedLoopCommandManager::save(LoopControlInfoPtr& ploopControlInfo) {
    if (mptimedLoopCommand != ploopControlInfo){
        mptimedLoopCommand = ploopControlInfo;
    }

    SafeDataFile file(mpath, O_WRONLY | O_CLOEXEC | O_CREAT);
    file.write(&*mptimedLoopCommand, LoopControlInfo::computeByteSize(mptimedLoopCommand->length));
    file.syncToPersistence();

    return true;
}



LoopControlInfoPtr& TimedLoopCommandManager::getDefaultTimedInfo(LoopControlInfoPtr& loopControlInfoPtr) {
    const LoopSize_t size = LoopManagerSingleton::instance().updatePortCount();
    loopControlInfoPtr.reset(new(size) LoopControlInfo(size, LoopStatus::TIMER_ON), LoopControlInfo::releaseMemory);
    loopControlInfoPtr->commandType = LoopCommandType::TIMED_COMMAND;
    return loopControlInfoPtr;
}



bool TimedLoopCommandManager::clear(){
    mptimedLoopCommand.reset();

    ::remove(mpath.c_str());

    return true;
}




